#!/usr/bin/env ruby  
# encoding: utf-8
require File.expand_path("../file_writer", __FILE__)
require "yaml"
require "active_record"
require "pry"

ADMIN_PATH = File.expand_path("../", __FILE__)
ProjectPath = File.expand_path("../", __FILE__)
Config = YAML.load_file(File.expand_path("../config.yml", __FILE__))
LOCALE_NAME = Config["locale_name"]
SCOPE = Config["scope"]


action = ARGV.shift
gtype = ARGV.shift

def new_project(project_name, theme)
  system("rails new #{project_name} --skip-bundle") unless Dir.exist?(project_name)
  init_gemfile(project_name)
  system("cd #{project_name} && bundle install") unless File.exist?(gemfile(project_name) + ".lock")
  copy_templates(project_name, theme)
  init_config_application(project_name)
  init_db(project_name)
  # run("rails g awesome_form_attributes:config", project_name)
end

def gemfile(project_name)
  "#{project_name}/Gemfile"
end

def init_gemfile(project_name)
  f = FileWriter.new(gemfile(project_name))
  f.replace("rubygems","ruby.taobao")
   .replace("'sqlite3'", "'mysql2', '~> 0.3.18'")
   .insert("gem 'awesome_form_attributes', '1.2.4'", -1)
   .insert("gem 'slim-rails'", -1)
   .insert("gem 'bootstrap-sass', '~> 3.2.0'", -1)
   .insert("gem 'kaminari'", -1)
   .insert("gem 'bcrypt'", -1)
   .insert("gem 'pry'", -1)
  f.save!
end

def init_config_application(project_name)
  f = FileWriter.new("#{project_name}/config/application.rb")
  f.replace("SunAdmin", ActiveSupport::Inflector.classify(project_name))
  f.save!
end

def init_db(project_name, use_mysql = true)
  if use_mysql
    db_c = Config["database"]
    default = {"username" => db_c["user"], "database" => [db_c["name"], project_name].compact.join("_"), 
               "password" => db_c["password"], "adapter" => "mysql2"}
    db_file = "#{project_name}/config/database.yml"
    db_config = YAML.load_file(db_file)
    db_config.values.map{|k| k.merge!(default)}
    File.open(db_file, 'w'){|f| YAML.dump(db_config, f)}  
  end
  %w(drop create migrate seed).map {|action| run("rake db:#{action}", project_name) }
end

def rewrite_yaml(file)
  datas = YAML.load_file(file)
  yield datas
  File.open(file, 'w'){|f| YAML.dump(datas, f)}  
end

def copy_templates(project_name, theme)
  base = "#{ADMIN_PATH}/admin/"
  files = ["common","themes/#{theme}"]
  files.map {|f| system("cp -rf #{base}#{f}/* #{project_name}/")}
end

def run(command, path = nil)
  return system("cd #{path} && bundle exec #{command}") if path
  system("bundle exec #{command}")
end

def generate_model(args = [])
  return puts "please input the model" if args.empty?
  model, model_title = args.shift.split(":")
  return puts "Plese input the Chinese title for model #{model}:" if model_title.nil?
  table = ActiveSupport::Inflector.pluralize(model)
  puts "Begin to generate model and to db ... #{model}"  
  normal_model_g, titles = [], []
  column_with_titles = {}
  args.each do |column|
    cname, ctype, ctitle = cs = column.split(":")
    raise "Params is not correct" if cs.size != 3
    column_with_titles[cname] = ctitle
    normal_model_g << "#{cname}:#{ctype}"
    titles << ctitle
  end
  run("rails g model #{model} #{normal_model_g.join(" ")} --force")
  run("rake db:migrate") rescue puts("Db Error!!") 
  config_routes(table)
  generate_controller(table)
  config_model_to_local(model, table, model_title, column_with_titles)
  config_model_to_view(table)
end

def check_model_params(cs)
   return "some params in thie model probily are incorrect" if cs.size != 3
   return "format are incorrect" if cs.any?{|c| !(c[1] =~ /[a-z]+/)}
   false 
end

def config_routes(table)
  f = FileWriter.new("config/routes.rb")
  position = 1 
  position = f.search_certain_str("namespace :#{SCOPE}") + 1 if !SCOPE.empty?
  empty_str = " " * (SCOPE.empty? ? 2 : 4)
  f.insert("#{empty_str}resources :#{table}", position)
  f.save!
  puts "Add to Routes Ready!"  
end

def config_model_to_local(model, table, model_title, column_with_titles)
  puts "Begin to config in locales... #{table}"  
  rewrite_yaml("config/locales/#{LOCALE_NAME}.yml") do |datas|
    datas[LOCALE_NAME]["activerecord"]["models"].merge!(model => model_title)
    datas[LOCALE_NAME].merge!(table => model_title + "管理")
    datas[LOCALE_NAME].merge!(model => model_title)
    datas[LOCALE_NAME]["activerecord"]["attributes"].merge!(model => column_with_titles)
  end
end

def generate_controller(table)
  puts "Begin to config in controllers... #{table}"  
  controllers_dir = File.join("app", "controllers", SCOPE)
  system("mkdir -p #{controllers_dir}")
  f = FileWriter.new(File.join(controllers_dir, "#{table}_controller.rb"))
  scope = ActiveSupport::Inflector.classify(SCOPE)
  f.insert("class #{[scope, ActiveSupport::Inflector.titleize(table).gsub(/\s+/,"")].join("::")}Controller < SunAdminBaseController",-1)
  f.insert("end",-1)
  f.save!
end

def config_model_to_view(table)
  puts "Begin to config in views... #{table}"  
  f = FileWriter.new("app/helpers/application_helper.rb")
  pos = f.search_line_in_method("top_menus","menus = ")
  f.insert(" " * (f.lines[pos] =~ /\s[a-z]+/) + "{'#{table}' => ''},", pos + 1)
  f.save!
rescue
  puts "Can not find method: top_menus, You need to config it by hand"
end

if action == "new"
  raise "Sorry, Sun Admin don't supprt ruby #{RUBY_VERSION}" if RUBY_VERSION.split(".")[0].to_i < 2
  theme = ARGV.shift || "bootstrap"
  raise "There must be a project name" if gtype.nil?
  new_project(gtype, theme)
else
  if gtype == "model"
    generate_model(ARGV)
  elsif gtype == "migration"
    migration = ARGV
    puts "Begin Generate Migration ... "  
  end
end
